////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
//    you must not claim that you wrote the original software.
//    If you use this software in a product, an acknowledgment
//    in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
//    and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////

#ifndef CASAENGINE_WINDOW_H
#define CASAENGINE_WINDOW_H

////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <Window/Event.h>
#include <Input/Input.h>
#include <Window/VideoMode.h>
#include <Window/WindowHandle.h>
#include <Window/WindowListener.h>
#include <Window/WindowSettings.h>
#include <Window/WindowStyle.h>
#include "NonCopyable.h"
#include <queue>
#include <string>


namespace CasaEngine
{
namespace priv
{
    class WindowImpl;
}

////////////////////////////////////////////////////////////
/// Window is a rendering window ; it can create a new window
/// or connect to an existing one
////////////////////////////////////////////////////////////
class CASAENGINE_EXPORT Screen : public WindowListener, NonCopyable
{
public :

    ////////////////////////////////////////////////////////////
    /// Default constructor
    ///
    ////////////////////////////////////////////////////////////
    Screen();

    ////////////////////////////////////////////////////////////
    /// Destructor
    ///
    ////////////////////////////////////////////////////////////
    virtual ~Screen();

    ////////////////////////////////////////////////////////////
    /// Create (or recreate) the window
    ///
    /// \param Mode :        Video mode to use
    /// \param Title :       Title of the window
    /// \param WindowStyle : Window style, see CasaEngine::Style (Resize | Close by default)
    /// \param Params :      Creation parameters (see default constructor for default values)
    ///
    ////////////////////////////////////////////////////////////
    void Create(VideoMode Mode, const std::string& Title, unsigned long WindowStyle = Style::Resize | Style::Close, const WindowSettings& Params = WindowSettings());

    ////////////////////////////////////////////////////////////
    /// Get the width of the rendering region of the window
    ///
    /// \return Width in pixels
    ///
    ////////////////////////////////////////////////////////////
    unsigned int GetWidth() const;

    ////////////////////////////////////////////////////////////
    /// Get the height of the rendering region of the window
    ///
    /// \return Height in pixels
    ///
    ////////////////////////////////////////////////////////////
    unsigned int GetHeight() const;

    ////////////////////////////////////////////////////////////
    /// Get the creation settings of the window
    ///
    /// \return Structure containing the creation settings
    ///
    ////////////////////////////////////////////////////////////
    const WindowSettings& GetSettings() const;

    ////////////////////////////////////////////////////////////
    /// Get the event on top of events stack, if any, and pop it
    ///
    /// \param EventReceived : Event to fill, if any
    ///
    /// \return True if an event was returned, false if events stack was empty
    ///
    ////////////////////////////////////////////////////////////
    bool GetEvent(SystemEvent& EventReceived);

    ////////////////////////////////////////////////////////////
    /// Enable / disable vertical synchronization
    ///
    /// \param Enabled : True to enable v-sync, false to deactivate
    ///
    ////////////////////////////////////////////////////////////
    void UseVerticalSync(bool Enabled);
	

    ////////////////////////////////////////////////////////////
    /// Get the input manager of the window
    ///
    /// \return Reference to the input
    ///
    ////////////////////////////////////////////////////////////
    Input* GetInput();

    ////////////////////////////////////////////////////////////
    /// Limit the framerate to a maximum fixed frequency
    ///
    /// \param Limit : Framerate limit, in frames per seconds (use 0 to disable limit)
    ///
    ////////////////////////////////////////////////////////////
    void SetFramerateLimit(unsigned int Limit);

    ////////////////////////////////////////////////////////////
    /// Get time elapsed since last frame
    ///
    /// \return Time elapsed, in seconds
    ///
    ////////////////////////////////////////////////////////////
    float GetFrameTime() const;

    ////////////////////////////////////////////////////////////
    /// Change the joystick threshold, ie. the value below which
    /// no move event will be generated
    ///
    /// \param Threshold : New threshold, in range [0, 100]
    ///
    ////////////////////////////////////////////////////////////
    void SetJoystickThreshold(float Threshold);

private :

    ////////////////////////////////////////////////////////////
    /// Called after the window has been created
    ///
    ////////////////////////////////////////////////////////////
    virtual void OnCreate();

    ////////////////////////////////////////////////////////////
    /// /see WindowListener::OnEvent
    ///
    /// \param EventReceived : Event received
    ///
    ////////////////////////////////////////////////////////////
    virtual void OnEvent(const SystemEvent& EventReceived);

    ////////////////////////////////////////////////////////////
    /// Initialize internal window
    ///
    /// \param Impl : New internal window implementation
    ///
    ////////////////////////////////////////////////////////////
    void Initialize(priv::WindowImpl* Impl);

    ////////////////////////////////////////////////////////////
    // Member data
    ////////////////////////////////////////////////////////////
    priv::WindowImpl* myWindow;         ///< Platform-specific implementation of window
    std::queue<SystemEvent> myEvents;         ///< Queue of received events
    Input             myInput;          ///< Input manager connected to window
    WindowSettings    mySettings;       ///< Creation settings of the window
    float             myLastFrameTime;  ///< Time elapsed since last frame
    bool              myIsExternal;     ///< Tell whether the window is internal or external (created by SFML or not)
    unsigned int      myFramerateLimit; ///< Current framerate limit
};

} // namespace CasaEngine


#endif // CASAENGINE_WINDOW_H
